﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.IO.Ports;
using System.Timers;

namespace serial_debuger
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Uart_cmd u_cmd;
        public struct Uart_cmd
        {
            public const UInt16 sof = 0x3773;
            public byte u_cmd_or_resp;
            public UInt32 addr;
            public UInt32 data;
            public byte sum;
            public const UInt16 eof = 0xd55d;
        };
        public byte cal_sum(Uart_cmd u_cmd_frame)
        {
            byte sum = 0;
            byte[] arry=new byte[11];

            arry[0] = 0x37;
            arry[1] = 0x73;

            //cmd or status
            arry[2] = (byte)(u_cmd_frame.u_cmd_or_resp & 0xFF);
            //addr
            arry[3] = (byte)((u_cmd_frame.addr & 0xFF) );
            arry[4] = (byte)((u_cmd_frame.addr & 0xFF00) >> 8);
            arry[5] = (byte)((u_cmd_frame.addr & 0xFF0000) >> 16);
            arry[6] = (byte)((u_cmd_frame.addr & 0xFF000000) >> 24);
            //data
          
            arry[7] = (byte)((u_cmd_frame.data & 0xFF));
            arry[8] = (byte)((u_cmd_frame.data & 0xFF00) >> 8);
            arry[9] = (byte)((u_cmd_frame.data & 0xFF0000) >> 16);
            arry[10] = (byte)((u_cmd_frame.data & 0xFF000000) >> 24);

            foreach(byte byte_dat in arry)
            {
                sum += byte_dat;
            }

            return sum;
            



        }
        



        private SerialPort ComDevice = new SerialPort();
         Thread autosend_thread;
        private void Form1_Load(object sender, EventArgs e)
        {

            portInit();

            radioButton_tx_hex.Checked = true;
            //radioButton_rx_hex.Checked = true;
            radioButton_rx_ascii.Checked = true;

            comboBox_ports.SelectedItem = 1;

            //autosend_thread = new Thread(autoSendData);
            //// autosend_thread.IsBackground = true;
            //autosend_thread.Start();

            Console.WriteLine("pass autosend_thread.Start()");

            Form1.CheckForIllegalCrossThreadCalls = false;

            autoSendTimer = new System.Timers.Timer();

            checkBox_autosend.Enabled = ComDevice.IsOpen;
            button_send.Enabled = ComDevice.IsOpen;

            comboBox_cmd.SelectedIndex = 0;
            comboBox_addr.SelectedIndex = 0;
            comboBox_data.SelectedIndex = 0;
            tabControl1.SelectedIndex = 1;

        }

        private void Form1_MouseClick(object sender, MouseEventArgs e)
        {
            
            
        }

        public void portInit()
        {
            comboBox_ports.Items.AddRange(SerialPort.GetPortNames());
            if(comboBox_ports.Items.Count>0)
            {
                comboBox_ports.SelectedIndex = 0;
            }
            //串口参数配置
            comboBox_baudrate.SelectedIndex = 4;
            comboBox_databits.SelectedIndex = 0;
            comboBox_parity.SelectedIndex = 0;
            comboBox_stopbits.SelectedIndex = 0;

            ComDevice.DataReceived += new SerialDataReceivedEventHandler(Com_DataReceived);//绑定事件

        }
        public void openPort()
        {

            if(comboBox_ports.Items.Count<=0)
            {
                MessageBox.Show("没有发现串口,请检查线路！");
                return;
            }

            if(ComDevice.IsOpen==false)
            {

                ComDevice.PortName = comboBox_ports.SelectedItem.ToString();
                ComDevice.BaudRate = Convert.ToInt32( comboBox_baudrate.SelectedItem.ToString());
                ComDevice.Parity = (Parity)Convert.ToInt32(comboBox_parity.SelectedIndex.ToString());
                ComDevice.DataBits= Convert.ToInt32(comboBox_databits.SelectedItem.ToString());
                ComDevice.StopBits = (StopBits)Convert.ToInt32(comboBox_stopbits.SelectedItem.ToString());


                try
                {
                    ComDevice.Open();
                    //发送使能
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
        }

        public void closePort()
        {
            try
            {

                ComDevice.Close();

            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }
        public void refreshComboBoxEditability()
        {

            comboBox_ports.Enabled = !ComDevice.IsOpen;
            comboBox_baudrate.Enabled = !ComDevice.IsOpen;
            comboBox_parity.Enabled = !ComDevice.IsOpen;
            comboBox_databits.Enabled = !ComDevice.IsOpen;
            comboBox_stopbits.Enabled = !ComDevice.IsOpen;

            checkBox_autosend.Enabled = ComDevice.IsOpen;
            button_send.Enabled = ComDevice.IsOpen;

        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool SendData(byte[] data)
        {
            if(ComDevice.IsOpen)
            {
                try
                {
                    ComDevice.Write(data, 0, data.Length);
                    return true;
                }
                catch(Exception ex)
                {
                    MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("串口未打开", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
            return false;
        }
        private void button_openPort_Click(object sender, EventArgs e)
        {
            openPort();
            refreshComboBoxEditability();
        }

        private void button_closePort_Click(object sender, EventArgs e)
        {
            closePort();
            refreshComboBoxEditability();
        }
        public byte[] dataTrans()
        {
            byte[] sendData = null;

            if (radioButton_tx_hex.Checked)
            {
                sendData = strToHexByte(richTextBox_send.Text.Trim());
            }
            else if (radioButton_tx_ascii.Checked)
            {
                sendData = Encoding.ASCII.GetBytes(richTextBox_send.Text.Trim());
            }

            return sendData;
        }
        private void button_send_Click(object sender, EventArgs e)
        {
            byte[] sendData = dataTrans();

            


            if (this.SendData(sendData))//发送数据成功计数
            {
                label_tx_cnt.Invoke(new MethodInvoker(delegate
                {
                    label_tx_cnt.Text = (int.Parse(label_tx_cnt.Text) + richTextBox_send.Text.Length).ToString();
                }));
            }
            else

            {
                Console.WriteLine("发送失败");
            }


        }

        /// <summary>
        /// 字符串转换16进制字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        private byte[] strToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
                hexString += " ";
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Replace(" ", ""), 16);
            return returnBytes;
        }


        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Com_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte[] ReDatas = new byte[ComDevice.BytesToRead];
            ComDevice.Read(ReDatas, 0, ReDatas.Length);//读取数据
            this.AddData(ReDatas);//输出数据
        }

        /// <summary>
        /// 添加数据
        /// </summary>
        /// <param name="data">字节数组</param>
        public void AddData(byte[] data)
        {
            if (radioButton_rx_hex.Checked)
            {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                {
                    sb.AppendFormat("{0:x2}" + " ", data[i]);
                }
                AddContent(sb.ToString().ToUpper());
            }
            else if (radioButton_rx_ascii.Checked)
            {
                AddContent(new ASCIIEncoding().GetString(data));
            }
            

            
            label_rx_cnt.Invoke(new MethodInvoker(delegate
            {
                label_rx_cnt.Text = (int.Parse(label_rx_cnt.Text) + data.Length).ToString();
            }));
        }

        /// <summary>
        /// 输入到显示区域
        /// </summary>
        /// <param name="content"></param>
        private void AddContent(string content)
        {
            this.BeginInvoke(new MethodInvoker(delegate
            {
                if (checkBox_autoline.Checked && richTextBox_recv.Text.Length > 0)
                {
                    richTextBox_recv.AppendText("\r\n");
                }
                richTextBox_recv.AppendText(content);
            }));

            this.richTextBox_recv.Focus();
            this.richTextBox_recv.Select(this.richTextBox_recv.TextLength, 0);
            this.richTextBox_recv.ScrollToCaret();
        }
        bool autoSendTask_exist = false;
        private System.Timers.Timer autoSendTimer;
        private void checkBox_autosend_CheckedChanged(object sender, EventArgs e)
        {
            if(checkBox_autosend.Checked && autoSendTask_exist==false)
            {
                
                
                autoSendTimer.Enabled = true;
                autoSendTimer.Interval = (int)numericUpDown1.Value; //执行间隔时间,单位为毫秒; 
                autoSendTimer.Start();
                autoSendTimer.Elapsed += new System.Timers.ElapsedEventHandler(autoSendData_timered);

                autoSendTask_exist = true;
            }
            else if(checkBox_autosend.Checked == false && autoSendTask_exist == true)
            {
                autoSendTimer.Enabled = false;
                autoSendTask_exist = false;
            }
        }
        public static void Delay(int milliSecond)
        {
            int start = Environment.TickCount;
            while (Math.Abs(Environment.TickCount - start) < milliSecond )//毫秒
            {
                Application.DoEvents();//可执行某无聊的操作
            }


        }
        public void autoSendData_timered(object source, ElapsedEventArgs e)
        {
           

                //Console.WriteLine("enter autoSendData");
                if (checkBox_autosend.Checked)
                {
                    byte[] sendData = dataTrans();

                    if (this.SendData(sendData))//发送数据成功计数
                    {
                        label_tx_cnt.Invoke(new MethodInvoker(delegate
                        {
                            label_tx_cnt.Text = (int.Parse(label_tx_cnt.Text) + richTextBox_send.Text.Length).ToString();
                        }));
                    }
                    



                }

            
        }
        public void autoSendData()
        {
            while(true)
            {

                //Console.WriteLine("enter autoSendData");
                if (checkBox_autosend.Checked)
                {
                    byte[] sendData = dataTrans();

                    if (this.SendData(sendData))//发送数据成功计数
                    {
                        label_tx_cnt.Invoke(new MethodInvoker(delegate
                        {
                            label_tx_cnt.Text = (int.Parse(label_tx_cnt.Text) + richTextBox_send.Text.Length).ToString();
                        }));
                    }
                    if((int)numericUpDown1.Value>0)
                    {
                        Delay((int)numericUpDown1.Value);
                    }
                    else
                    {
                        Delay(1000);
                    }
                        


                }

            }
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            autoSendTimer.Stop();
            autoSendTimer.Enabled = true;
            autoSendTimer.Interval = (int)numericUpDown1.Value; //执行间隔时间,单位为毫秒; 
            autoSendTimer.Start();
            autoSendTimer.Elapsed += new System.Timers.ElapsedEventHandler(autoSendData_timered);
        }

        private void button_clearText_Click(object sender, EventArgs e)
        {
            richTextBox_recv.Text = "";
        }

        private void label9_Click(object sender, EventArgs e)
        {

        }

        private void button_send_ucmd_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(comboBox_addr.Text);

           
            byte[] sendData_addr = null;
            byte[] sendData_data = null;

            byte[] sendData = new byte[14];

            //we need to send hex data as cmd
            sendData_addr = strToHexByte(comboBox_addr.Text.Trim());
            sendData_data = strToHexByte(comboBox_data.Text.Trim());


            sendData[0] = 0x37;
            sendData[1] = 0x73;



            switch (comboBox_cmd.Text)
            {
                case "write_reg":
                    sendData[2] = 0x0;
                    break;
                case "read_reg":
                    sendData[2] = 0x1;
                    break;
                    
                case "read_spec_regs":
                    sendData[2] = 0x2;
                    break;
                case "reg_file_write":
                    sendData[2] = 0x3;
                    break;
                case "reg_file_read":
                    sendData[2] = 0x4;
                    break;

            }
            for(int i=0; i<4; i++)
            {
                sendData[i + 3] = sendData_addr[i];
                sendData[i + 7] = sendData_data[i];
            }

            

            byte sum = 0;
            for(int i =0;i<11;i++)
            {
                
                sum += sendData[i];
            }
            sendData[11] = sum;
            sendData[12] = 0xd5;
            sendData[13] = 0x5d;

            foreach (byte n in sendData)
            {
                Console.WriteLine("{0:X000}", n);
                
            }

            this.SendData(sendData);
            label_ucmd_status.Text = "CMD: " + comboBox_cmd.Text + "\nADDR: 0x" + comboBox_addr.Text + "\nDATA: 0x" + comboBox_data.Text;
        }
    }

    public class SerialDebugger
    {
       
        
       

    }
}
